﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProgNetComponents.Log;
using ProgNetComponents.Data;
using System.Data;

namespace ProgNetDxComponents.ExtenderProviders.Browsers
{
    public class BrowserConfigRecord
    {
        public int MinForDialog
        {
            get;
            set;
        }
        public BrowserConfigDisplayType DisplayType
        {
            get;
            set;
        }

        public SimpleRecordState RecordState
        {
            get;
            set;
        }
    }

    public abstract class BrowserConfigReader
    {
        private Logger _Logger;
        protected Logger Logger
        {
            get
            {
                if (_Logger == null)
                    return Logger.Default;
                return _Logger;
            }
            set { _Logger = value; }
        }

        protected BrowserDataGrabberBase Grabber;

        public BrowserConfigReader(BrowserDataGrabberBase grabber)
        {
            Grabber = grabber;
        }
        protected Dictionary<string, BrowserConfigRecord> Configs = new Dictionary<string, BrowserConfigRecord>();
        public BrowserDisplayType GetDisplayType(string browserName, string additionalFilter = null)
        {
            Browser br = BrowserCache.GetBrowser(browserName, false);
            if(br.DisplayType != BrowserDisplayType.ConfigSpecified)
                return br.DisplayType;
            if(br.ConfigGroup.IsNull())
                return BrowserDisplayType.LookUp;

            string name = br.ConfigGroup;

            if (name.IsNotNull() && Configs.ContainsKey(name))
            {
                BrowserConfigDisplayType r = Configs[name].DisplayType;
                switch (r)
                {
                    case BrowserConfigDisplayType.ComboLookUp:
                        return BrowserDisplayType.ComboLookUp;
                    case BrowserConfigDisplayType.Dialog:
                        return BrowserDisplayType.Dialog;
                    case BrowserConfigDisplayType.LookUp:
                        return BrowserDisplayType.LookUp;
                    case BrowserConfigDisplayType.Auto:
                        int i = Grabber.GetRecordCountFromDB(browserName, additionalFilter);
                        if (i >= Configs[name].MinForDialog)
                            return BrowserDisplayType.Dialog;
                        break;
                }
            }
            return BrowserDisplayType.LookUp;
        }
        
        public virtual void AddConfig(string groupName)
        {
            if (groupName.IsNotNull() &&
                !Configs.ContainsKey(groupName))
            {
                BrowserConfigRecord r = new BrowserConfigRecord();
                r.DisplayType =  BrowserConfigDisplayType.Auto;
                r.MinForDialog = 50;
                Configs.Add(groupName, r);
            }
        }

        /// <summary>
        /// Gets browser configuration and updates Configs dictionary
        /// </summary>
        public abstract bool ReadConfigs();
        /// <summary>
        /// Updates browser configuration
        /// </summary>
        public abstract bool SaveConfigs();
    }

    public abstract class BrowserConfigReaderDB : BrowserConfigReader
    {
        private string _TableName;
        private string _BrowserGroupColumn;
        private string _DisplayTypeColumn;
        private string _MinForDialogColumn;
        private DataTable _ConfigsTable = null;
        protected DataTable ConfigsTable
        {
            get
            {
                if (_ConfigsTable == null)
                    _ConfigsTable = CreateTable();
                return _ConfigsTable;
            }
        }
        public string TableName
        {
            get { return _TableName; }
        }

        public string BrowserGroupColumn
        {
            get { return _BrowserGroupColumn; }
        }

        public string DisplayTypeColumn
        {
            get { return _DisplayTypeColumn; }
        }

        public string MinForDialogColumn
        {
            get { return _MinForDialogColumn; }
        }

        public BrowserConfigReaderDB(BrowserDataGrabberBase grabber, string TableName,
            string BrowserGroupColumn, string DisplayTypeColumn, string MinForDialogColumn,
            string connectionstring = null)
            : base(grabber)
        {
            _TableName = TableName;
            _BrowserGroupColumn = BrowserGroupColumn;
            _DisplayTypeColumn = DisplayTypeColumn;
            _MinForDialogColumn = MinForDialogColumn;
            if (connectionstring.IsNotNull())
            {
                Manager.ConnectionString = connectionstring;
                Manager.UseGlobalConnectionString = false;
            }
        }

        private DataManager _Manager = null;
        protected DataManager Manager
        {
            get
            {
                if (_Manager == null)
                    _Manager = CreateManager();
                return _Manager;
            }
        }
        /// <summary>
        /// Creates DataManager
        /// </summary>
        /// <returns></returns>
        protected abstract DataManager CreateManager();
        protected virtual DataTable CreateTable()
        {
            DataTable dt = new DataTable(TableName);
            dt.Columns.Add(BrowserGroupColumn);
            dt.Columns.Add(DisplayTypeColumn);
            dt.Columns.Add(MinForDialogColumn, typeof(int));
            return dt;
        }

        protected virtual string GetSelectString()
        {
            return "SELECT " + BrowserGroupColumn + ", " + DisplayTypeColumn + "," + MinForDialogColumn + " FROM " + TableName;
        }
        
        public override bool ReadConfigs()
        {
            if (!Manager.FillTable(ConfigsTable, GetSelectString()))
            {
                Logger.Log(Manager.LastException, this.GetType().FullName + ".ReadConfigs()");
                return false;
            }
            string group = "";
            foreach (DataRow r in ConfigsTable.Rows)
            {
                group = r[this.BrowserGroupColumn].AsString();
                if (Configs.ContainsKey(group))
                {
                    Configs[group].DisplayType = r[DisplayTypeColumn].AsEnum<BrowserConfigDisplayType>();

                    if (Configs[group].DisplayType == BrowserConfigDisplayType.Auto)
                        Configs[group].MinForDialog = r[MinForDialogColumn].AsInt(50);
                    else
                    {
                        Configs[group].MinForDialog = -1;
                        r.SetColumnValue(MinForDialogColumn, -1);
                    }
                }
            }
            return true;
        }

        public override bool SaveConfigs()
        {
            DataRow row = null;
            foreach (KeyValuePair<string, BrowserConfigRecord> kvp in Configs)
            {
                if (kvp.Value.RecordState != SimpleRecordState.Unchanged)
                {
                    if (kvp.Value.RecordState == SimpleRecordState.Added)
                        row = ConfigsTable.NewRow();
                    
                    row[this.BrowserGroupColumn] = kvp.Key;
                    row[this.DisplayTypeColumn] = kvp.Value.DisplayType.ToString();
                    if (kvp.Value.DisplayType == BrowserConfigDisplayType.Auto)
                        row[this.MinForDialogColumn] = kvp.Value.MinForDialog;
                    else
                        row[this.MinForDialogColumn] = DBNull.Value;
                    
                    if (kvp.Value.RecordState == SimpleRecordState.Added)
                    ConfigsTable.Rows.Add(row);
                }
            }
            if (Manager.UpdateTable(ConfigsTable))
            {
                foreach (KeyValuePair<string, BrowserConfigRecord> kvp in Configs)
                {
                    kvp.Value.RecordState = SimpleRecordState.Unchanged;
                }
                ConfigsTable.AcceptChanges();
                return true;
            }
            else
            {
                Logger.Log(Manager.LastException, this.GetType().FullName + ".UpdateConfigs()");
            }
            return false;
        }
    }

    public class BrowserConfigReaderSqlCe : BrowserConfigReaderDB
    {
        public BrowserConfigReaderSqlCe(BrowserDataGrabberBase grabber, string TableName,
            string BrowserGroupColumn, string DisplayTypeColumn, string MinForDialogColumn,
            string connectionstring = null)
            : base(grabber, TableName, BrowserGroupColumn,
            DisplayTypeColumn, MinForDialogColumn, connectionstring)
        {

        }
        protected override DataManager CreateManager()
        {
            return new ProgNetComponents.Data.SqlCe.SqlCeDataManager();
        }
    }
}
